package com.mahees.portfolio.controller

import org.codehaus.groovy.grails.web.json.JSONArray;
import org.codehaus.groovy.grails.web.json.JSONObject;

import com.mahees.portfolio.controller.DevelopmentToolCommand;
import com.mahees.portfolio.domain.DevelopmentTool;
import com.mahees.portfolio.domain.DevelopmentToolTypeEnum;

import grails.converters.*;
import grails.test.*
import grails.web.JSONBuilder;

class DevelopmentToolControllerTests extends ControllerUnitTestCase {

	List<DevelopmentTool> developmentTools
	DevelopmentToolCommand developmentToolCommandObj
	String inputJson
	def inputJsonParams;

	protected void setUp() {
		super.setUp()

		controller.metaClass.render = { Map map, Closure c ->
			mockResponse.status = map.status
			new JSONBuilder().build(c).render(mockResponse)
		}
		mockRequest.contentType = 'application/json';
		//http://grails.org/doc/2.0.x/ref/Servlet%20API/request.html
		controller.request.format = 'json'
		controller.params.format = 'json'
		controller.request.contentType = "application/json"
		//controller.jsonaction()

		mockDomain(DevelopmentTool);

		developmentTools = [
			new DevelopmentTool(name : 'Eclipse',
			description : 'Built in Java, many plugins available',
			url : 'http://www.eclipse.org/',
			toolType : DevelopmentToolTypeEnum.IDE
			).save(failOnError : true),
			new DevelopmentTool(name : 'SpringSource Tool Suite',
			url : 'http://www.springsource.com/developer/sts',
			toolType : DevelopmentToolTypeEnum.IDE
			).save(failOnError : true)
		]

		developmentToolCommandObj = new DevelopmentToolCommand();
		mockForConstraintsTests(DevelopmentToolCommand, [developmentToolCommandObj]);

		inputJsonParams = [:];

	}

	String generateSaveInputJsonString(inputJsonParams) {
		inputJson = "{name : '${inputJsonParams.name}', description : '${inputJsonParams.description}', url : '${inputJsonParams.url}', toolType : '${inputJsonParams.toolType}'}"
		return inputJson;
	}

	protected void tearDown() {
		super.tearDown()
	}
	
	void testSave_SlightlyChanged_NamePassesCommandButFailsDomainValidationDuringSave_ThrowsValidationExAndRendersError() {
		inputJsonParams.name = 'this text is supposed to be under 50charbutover40'
		assert inputJsonParams.name.size() > 40
		assert inputJsonParams.name.size() < 50
		inputJsonParams.description = ''
		inputJsonParams.url = 'http://netbeans.org/'
		inputJsonParams.toolType = 'IDE'

		mockRequest.content = generateSaveInputJsonString(inputJsonParams);

		//changed here
		developmentToolCommandObj = controller.request.JSON

		assert developmentToolCommandObj.validate()

		controller.save(developmentToolCommandObj);

		assert controller.response.status == 500
		JSONObject result = JSON.parse(controller.response.contentAsString);
		assert result.message != ''
		assert result.fullMessage != ''
		assert result.errorList
		assert result.errorList.size() == 1
		assert result.errorList[0].field == 'name'
		assert result.errorList[0].value == 'this text is supposed to be under 50charbutover40'
		assert result.errorList[0].message
	}
	
	void testSave_NamePassesCommandButFailsDomainValidationDuringSave_ThrowsValidationExAndRendersError() {
		inputJsonParams.name = 'this text is supposed to be under 50charbutover40'
		assert inputJsonParams.name.size() > 40
		assert inputJsonParams.name.size() < 50
		inputJsonParams.description = ''
		inputJsonParams.url = 'http://netbeans.org/'
		inputJsonParams.toolType = 'IDE'

		mockRequest.content = generateSaveInputJsonString(inputJsonParams);

		//expected json marshaler to kick in and give me json
		def requestInputJson = controller.request.JSON
		developmentToolCommandObj.name = requestInputJson.name
		developmentToolCommandObj.description = requestInputJson.description
		developmentToolCommandObj.url = requestInputJson.url
		developmentToolCommandObj.toolType = requestInputJson.toolType

		assert developmentToolCommandObj.validate()

		controller.save(developmentToolCommandObj);

		assert controller.response.status == 500
		JSONObject result = JSON.parse(controller.response.contentAsString);
		assert result.message != ''
		assert result.fullMessage != ''
		assert result.errorList
		assert result.errorList.size() == 1 
		assert result.errorList[0].field == 'name'
		assert result.errorList[0].value == 'this text is supposed to be under 50charbutover40'
		assert result.errorList[0].message
	}
	
	void testSave_NameTooShort_CommandObjFailsRendersError() {
		inputJsonParams.name = 'N'
		inputJsonParams.description = ''
		inputJsonParams.url = 'http://netbeans.org/'
		inputJsonParams.toolType = 'IDE'

		mockRequest.content = generateSaveInputJsonString(inputJsonParams);

		//expected json marshaler to kick in and give me json
		def requestInputJson = controller.request.JSON
		developmentToolCommandObj.name = requestInputJson.name
		developmentToolCommandObj.description = requestInputJson.description
		developmentToolCommandObj.url = requestInputJson.url
		developmentToolCommandObj.toolType = requestInputJson.toolType

		assert !developmentToolCommandObj.validate()

		controller.save(developmentToolCommandObj);

		assert controller.response.status == 500
		JSONArray result = JSON.parse(controller.response.contentAsString);
		assert result.size() == 1
		assert result[0].value == 'N'
		assert result[0].field == 'name'
	}

	void testSave_HappyPath_AllValidatesAndSaves() {
		inputJsonParams.name = 'Netbeans'
		inputJsonParams.description = ''
		inputJsonParams.url = 'http://netbeans.org/'
		inputJsonParams.toolType = 'IDE'

		mockRequest.content = generateSaveInputJsonString(inputJsonParams);

		//expected json marshaler to kick in and give me json
		def requestInputJson = controller.request.JSON
		developmentToolCommandObj.name = requestInputJson.name
		developmentToolCommandObj.description = requestInputJson.description
		developmentToolCommandObj.url = requestInputJson.url
		developmentToolCommandObj.toolType = requestInputJson.toolType

		assert developmentToolCommandObj.validate()

		controller.save(developmentToolCommandObj);

		assert controller.response.status == 200
		assert DevelopmentTool.count() == 3
	}

	void testList_ReturnsAllValuesAsExpected() {
		controller.list();

		assert controller.response.status == 200
		JSONArray result = JSON.parse(controller.response.contentAsString);
		assert result.size() == 2;
		assert result[1].name == 'SpringSource Tool Suite';
		assert result[1].url == 'http://www.springsource.com/developer/sts';
		assert result[1].toolType == DevelopmentToolTypeEnum.IDE.type.toString();
	}

	void testList_NullDescription_returnsEmptyStringNotNullCheck() {
		controller.list();

		assert controller.response.status == 200
		JSONArray result = JSON.parse(controller.response.contentAsString);
		assert result.size() == 2;
		assert result[1].name == 'SpringSource Tool Suite';
		assert result[1].description == '';
		assert controller.response.status == 200
	}

	void testList_NotNullDescription_returnsEmptyStringNotNullCheck() {
		controller.list();

		assert controller.response.status == 200
		JSONArray result = JSON.parse(controller.response.contentAsString);
		assert result.size() == 2;
		assert result[0].name == 'Eclipse';
		assert result[0].description == 'Built in Java, many plugins available';
	}
}
